import fs from "fs";

import { ctx } from '../entrance/inter';
import color from '../utils/Color';
import RequestModel from './ctx/RequestModel';
import ResponseModel from './ctx/ResponseModel';
import { IncomingMessage, ServerResponse } from 'http';
import Request from "../interface/Request"
import Response from "../interface/Response"
import sugar from '../core/sugar';
import config from '../init/ConfigHandler';
import $path from "path";

/**
 * 请求上下文实体类
 * Context的模型，存储了ctx的类型和方法
 */
export = class Context implements ctx {
  // req,res 是原生的
  public req: IncomingMessage = null;
  public res: ServerResponse = null;
  // $req,$res 是保留的
  public $req: IncomingMessage = null;
  public $res: ServerResponse = null;
  // 框架封装的
  public request: Request = null;
  public response: Response = null;
  /** 获取cookie */
  public cookie: Function = Context._agent(this, "request", "cookie");
  /** 启动异步返回 */
  public startAsync: any = Context._agent(this, "response", "startAsync");
  /** 返回数据 */
  public body: any = Context._agent(this, "response", "body");
  /** 代理接口 */
  public proxy: any = Context._agent(this, "response", "proxy");
  /** 发送文件 */
  public sendFile: any = Context._agent(this, "response", "sendFile");
  /** 重定向 */
  public redirect: any = Context._agent(this, "response", "redirect");
  /** 间断性发送数据 */
  public echo: any = Context._agent(this, "response", "echo");
  /** 获取单个或所有数据 */
  public $all: any = null;
  /** 获取单个或所有数据 */
  public getParam: any = (key: string) => {
    if (key == undefined) {
      return this.$all();
    } else {
      return this.$all(key);
    }
  };
  filepath: string;

  /**
   * 构造方法
   */
  constructor(req: IncomingMessage, res: ServerResponse) {
    this.req = this.$req = req;
    this.res = this.$res = res;
    this.request = new RequestModel(this);
    this.response = new ResponseModel(this);
    res.on("end", () => { this.response.isClose = true; })
    res.on("error", (err) => {
      if (err.message === "write after end") {
        console.log(color("红色", "写入流已关闭，如需进行异步返回，请先开启异步 ctx.startAsync()\n\n"))
      } else {
        console.log(err)
      }
    })
  }

  /**
   * 代理一下类方法
   */
  static _agent(fun: any, methodName: string, methodName2: string) {
    return function (...a: any) {
      return fun[methodName][methodName2](...a);
    }
  }

  // 获取文件路径
  static getFilePath(ctx: Context): string {
    // 生成一盒路径
    let path = sugar.path(config.getAddress("public") + ctx.request.url);
    let state = path.endsWith("/");
    // 存在并且是一个文件
    if (fs.existsSync(path) && fs.statSync(path).isFile()) { return path }

    if (state && fs.existsSync(path + "index.html")) {
      return path + "index.html"
    }
    // 净化path
    if (!state && fs.existsSync(path + ".html")) {
      return path + ".html"
    };

    if (fs.existsSync(path + "/index.html")) {
      // 关闭重定向，开启会导致一个无限请求的bug
      return $path.join(path + "/index.html");
    };
    return null;
  }
}